import json
import time
import pandas
import matplotlib.pyplot as plt

import plotly as py
import plotly.figure_factory as ff

# 读取txt数据
import pandas as pd

file1 = open(r'附件一：航班与机位数据.txt')
reqdata1 = file1.read()
##将json数据转换成dict
jstr = json.loads(reqdata1)
jstr_flight = jstr['flight'] # [{},{}...]
jstr_gate = jstr['gate']

def add12h(a):
    timeArray = time.strptime(a, "%Y-%m-%d %H:%M:%S")
    timeStamp = time.mktime(timeArray)
    newtimeStamp = timeStamp + 43200
    newtimeArray = time.localtime(newtimeStamp)
    return time.strftime("%Y-%m-%d %H:%M:%S", newtimeArray)

# 航班数据预处理
newjstr_flight = []
for i in jstr_flight:
    if i['dtime'] == '':
        i['dtime'] = add12h(i['atime'])
    if i['dtime'] <= i['atime']:
        continue
    newjstr_flight.append(i)

# 设置贪心法制
newjstr_flight.sort(key=lambda k: k['atime'],reverse=True)  # 到港时间降序
# newjstr_flight.sort(key=lambda k: k['atime'],reverse=False)  # 到港时间升序
# newjstr_flight.sort(key=lambda k: k['dtime'],reverse=True)  # 离港时间降序
# newjstr_flight.sort(key=lambda k: k['dtime'],reverse=False)  # 离港时间升序
# 机位变为空
for i in newjstr_flight:
    i['ParkingGate'] = None
    # print(i['ParkingGate'], i['planeno'], i['aflightno'], i['dflightno'], i['atime'], i['dtime'],
    #       i['mdl'], i['Forg'], i['Fest'])


print('待分配航班条数：',len(jstr_flight))
print('机位个数：',len(jstr_gate))

# #############################准备工作#################################################
# 定义时间转换函数（到分钟）
def timed(a):
    timeArray = time.strptime(a, "%Y-%m-%d %H:%M:%S")
    timeStamp = int(time.mktime(timeArray)) / 60
    return timeStamp

# 定义函数判断时间是否冲突isTimeCollision
def isTimeCollision(a, b, c, d):
    if (b > c and b <= d) or (d > a and d <= b):
        return 1
    elif (a >= c and a < d) or (c >= a and c < b):
        return 1
    else:
        return 0


def isNeartimeCollision(a, b, c, d):
    if (abs(a - c) < 5) or (abs(b - d) < 5) or (abs(b - c) < 5) or (abs(a - d) < 5):
        return 1
    else:
        return 0


# 为每个停机位建立列表，存放停靠航班
for i in jstr_gate:
    i['flightset'] = []


# 输入一航班和所有机位，输出满足同机位间隔时间约束的可用机位
def get_time_available_gate(flight, or_gatelist, gatelist, t1):
    restgate = []
    for i in gatelist:
        iscollided = 0
        for j in or_gatelist:
            if i == j:
                for ii in j['flightset']:
                    if isTimeCollision(timed(ii['atime']), timed(ii['dtime']), timed(flight['atime']) - t1, timed(flight['dtime']) + t1) == 1:
                        iscollided = 1
        if iscollided == 0:
            restgate.append(i)
    return restgate


# 相邻机位约束  5min   [self]
def get_near_available_gate(flight, or_gatelist, gatelist):
    restgate = []
    for i in gatelist:
        neargate_flight = []
        iscollided = 0
        for j in or_gatelist:
            # print(j['flightset'])
            if j != i:
                if abs(int(i['ParkingGate']) - int(j['ParkingGate'])) == 1:
                    neargate_flight.extend(j['flightset'])
                    # print(neargate_flight)
        if len(neargate_flight) > 0:
            for ii in neargate_flight:
                if isNeartimeCollision(timed(flight['atime']), timed(flight['dtime']), timed(ii['atime']), timed(ii['dtime'])) == 1:
                    iscollided = 1
        if iscollided == 0:
            restgate.append(i)
    return restgate


def apron_type(flight,gatelist):
    restgate = []
    if flight['mdl'] == 'B737':
        restgate = gatelist
    else:
        for i in gatelist:
            if i['ParkingGate'] != '7':
                restgate.append(i)
    return restgate


# 区分近远机位
neargatelist = []
aprongatelist = []
for i in jstr_gate:
    if i['bridge'] == '1':
        neargatelist.append(i)
    else:
        aprongatelist.append(i)

# 开始分配
cnt = 0
for i in newjstr_flight:
    if i['ParkingGate'] == None:
        available_neargate = apron_type(i, neargatelist)
        available_neargate1 = get_near_available_gate(i, jstr_gate, available_neargate)
        available_neargate2 = get_time_available_gate(i, jstr_gate, available_neargate1, 15)
        if len(available_neargate2) > 0:
            available_neargate2.sort(key=lambda k: k['ParkingGate'], reverse=True)
            i['ParkingGate'] = available_neargate2[0]['ParkingGate']
            available_neargate2[0]['flightset'].append(i)
            cnt += 1
        else:
            # available_aprongate = apron_type(i, aprongatelist)
            available_aprongate1 = get_near_available_gate(i, jstr_gate, aprongatelist)
            available_aprongate2 = get_time_available_gate(i, jstr_gate, available_aprongate1, 15)
            if len(available_aprongate2) > 0:
                i['ParkingGate'] = available_aprongate2[0]['ParkingGate']
                available_aprongate2[0]['flightset'].append(i)

print('分配完毕:')
for i in newjstr_flight:
    print(i['ParkingGate'], i['planeno'], i['aflightno'], i['dflightno'], i['atime'], i['dtime'],
          i['mdl'], i['Forg'], i['Fest'])

print(cnt/81)
print(cnt)

'''-------------------甘特图matplotlib-------------------'''
plt.rcParams['font.sans-serif'] = ['SimHei']

for i in newjstr_flight:
    a = (timed(i['atime']) - timed("2018-10-22 00:00:00")) / 60
    b = (timed(i['dtime']) - timed("2018-10-22 00:00:00")) / 60
    plt.plot([a, b], [int(i['ParkingGate']), int(i['ParkingGate'])], linewidth=4,color='red')
    # 第一个参数是添加文字的x轴坐标
    # 第二个参数是添加文字的y轴坐标
    # 第三个参数是要显式的内容
    # alpha 设置字体的透明度
    # size 设置字体的大小
plt.xlabel('时间(min)')  # 横坐标轴的标题
plt.ylabel('停机位')  # 纵坐标轴的标题
plt.yticks(range(30))  # 设置横坐标轴的刻度为 0 到 10 的数组
plt.xticks(range(0,48,2))  # 设置横坐标轴的刻度为 0 到 10 的数组
plt.grid()  # 显示网格
plt.title('停机位分配结果')  # 图形的标题
plt.show()



# 导出excel
flight = pandas.DataFrame(newjstr_flight)
# # gate = pandas.DataFrame(jstr_gate)
flight.to_excel("flight1.xlsx", index=True, index_label='序号')
# gate.to_excel("gate1.xlsx", index=True, index_label='序号')


'''-------------------甘特图plotly-------------------'''
# flight.sort_values(by='ParkingGate', inplace=True, ascending=True)
# print(flight.head())
df = flight.rename(columns = {'ParkingGate':'Task',
                          'atime':'Start',
                          'dtime':'Finish'})
df.sort_values(by='Start', ascending=False)
fig = ff.create_gantt(df, show_colorbar=True, showgrid_x=True, showgrid_y=True, group_tasks=True)
fig.show()